/**
 * ChartActivator.java
 */
package com.pluginsacceptor.plugin.chart;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Observer;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.apache.log4j.Logger;

import com.pluginsacceptor.api.Activator;
import com.pluginsacceptor.plugin.chart.impl.GrapheurTabEntiers;
import com.pluginsacceptor.plugin.chart.impl.TableauEntierEtendu;
import com.pluginsacceptor.plugin.chart.impl.VueBar;
import com.pluginsacceptor.plugin.chart.model.ChartState;
import com.pluginsacceptor.plugin.chart.model.CurrentChartState;
import com.pluginsacceptor.utils.CommunicationUtils;

/**
 * The chart activator
 * This plugin will be inject to acceptor main panel
 *
 * This plugin doesn't send information to another plugin (addObserver() - not used)
 * This plugin receives information from another plugin (getObserver() - used)
 */
public class ChartActivator implements Activator {

    /** Logger */
    private static final Logger LOG = Logger.getLogger(ChartActivator.class);

    /** */
    private final List<CurrentChartState> charts = new ArrayList<CurrentChartState>();

    /** */
    private final List<TableauEntierEtendu> tableDesIntiers = new ArrayList<TableauEntierEtendu>();

    /** */
    private JMenu chartMenu;

    /** */
    private ChartComponent mainChartComponent;

    /** */
    private ChartCellChooserFrame chartCellChooserFrame;

    /**
     * {@inheritDoc}
     */
    @Override
    public JComponent activate(final String[] metadata) {
        LOG.info("Activate chart plugin");

        this.mainChartComponent = new ChartComponent();

        this.chartCellChooserFrame = new ChartCellChooserFrame(this.charts);
        this.chartCellChooserFrame.setVisible(false);

        createChartMenu(chartCellChooserFrame);

        createNewChartComponent();
        return this.mainChartComponent;
    }




    @Override
    public boolean deactivate() {
        LOG.info("Deactivate chart plugin");
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void addObserver(final Observer observer) {

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Observer getObserver() {
        return new ChartObserver(this.charts, this.tableDesIntiers);
    }

    @Override
    public JComponent getMenuItem() {
        return this.chartMenu;
    }


    public static void main(final String[] args) {
        final Activator activator = new ChartActivator();
        final JFrame frame = new JFrame("Chart debug");
        frame.setSize(800, 800);
        final JPanel panel = new JPanel();
        panel.add(new JTextField("Test"));
        panel.add(activator.activate(null));
        frame.add(panel, BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean load(final Object data) {
        boolean result = true;
        try {
            if (data instanceof List<?>) {
                clearChart();

                final List<List<String>> loadData = (List<List<String>>) data;

                for (final List<String> chartData : loadData) {
                    final CurrentChartState chartState = new CurrentChartState();
                    chartState.setChartState(ChartState.RECEIVED_NEW_DATA);

                    for (final String cell : chartData) {
                        if (CommunicationUtils.isCellData(cell)) {
                            ChartUtils.changeChartData(cell, chartState);
                        } else {
                            LOG.warn("Invalid data " + cell);
                            result = false;
                            break;
                        }
                    }
                    chartState.setChartState(ChartState.WAIT_UPDATE_DATA);
                    createNewChartComponent(chartState);
                    this.tableDesIntiers.get(this.tableDesIntiers.size() - 1)
                        .melange(chartState.getBarChartData());
                }
            } else {
                LOG.warn("Invalid load object " + data);
                result = false;
            }
        } catch (final Exception e) {
            LOG.error("Load is failed", e);
            result = false;
        }
        return result;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Object save() {
        final List<List<String>> savedCharts = new ArrayList<List<String>>();

        for (final CurrentChartState chartState : this.charts) {
            savedCharts.add(chartState.getBarChartData().getUsingDataCell());
        }
        return savedCharts;
    }

    /**
     * Create chart menu
     * @param chartCellChooserFrame the active chooser frame item
     */
    private void createChartMenu(final ChartCellChooserFrame chartCellChooserFrame) {
        this.chartMenu = new JMenu("Chart");

        final JMenuItem barChart = new JMenuItem("Bar chart");
        barChart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
              createNewChartComponent();
              charts.get(charts.size() - 1).setChartState(ChartState.RECEIVED_NEW_DATA);
              chartCellChooserFrame.setVisible(true);
            }
        });

        this.chartMenu.add(barChart);

        final JMenuItem cambaberChart = new JMenuItem("Camembert chart");
        cambaberChart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(final ActionEvent e) {
              createNewChartComponent(); // TODO need set cambaber type
              charts.get(charts.size() - 1).setChartState(ChartState.RECEIVED_NEW_DATA);
              chartCellChooserFrame.setVisible(true);
            }
        });

        this.chartMenu.add(cambaberChart);
    }


    /**
     * Create new chart component
     * @param chartState the new chart data
     */
    private void createNewChartComponent(final CurrentChartState chartState) {

        final TableauEntierEtendu table = new TableauEntierEtendu();
        final GrapheurTabEntiers chartComponent = new GrapheurTabEntiers(
            new VueBar(),
            table
        );
        table.addObserver(chartComponent);
        table.addObserver(chartCellChooserFrame.getObserver());

        this.charts.add(chartState);
        this.tableDesIntiers.add(table);

        this.mainChartComponent.addChart(chartComponent);
    }

    /**
     * Cleart chart data
     */
    private void clearChart() {
        this.charts.clear();
        this.tableDesIntiers.clear();
        this.mainChartComponent.removeAll();
    }

    /**
     * Create empty chart component
     */
    private void createNewChartComponent() {
        if (
            this.charts.isEmpty()
                || this.charts.get(this.charts.size() - 1).getBarChartData().getNumberDataColumn() > 0
        ) {
            createNewChartComponent(new CurrentChartState());
        }
    }
}
